/**
 * Copyright 2009 Sergio Bossa
 *
 *    Licensed under the Apache License, Version 2.0 (the "License");
 *    you may not use this file except in compliance with the License.
 *    You may obtain a copy of the License at
 *
 *        http://www.apache.org/licenses/LICENSE-2.0
 *
 *    Unless required by applicable law or agreed to in writing, software
 *    distributed under the License is distributed on an "AS IS" BASIS,
 *    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 *    See the License for the specific language governing permissions and
 *    limitations under the License.
 */
package com.googlecode.actorom;

import java.util.concurrent.TimeUnit;

/**
 * Actors are the main abstraction implementing message-passing concurrency.
 * <br><br>
 * Messages sent to an actor are <b>asynchronously</b> and <b>sequentially</b> processed in <b>FIFO</b> order.
 * An actor, so, can have its own state which will never be shared with other actors, nor concurrently accessed.
 * <br><br>
 * In order to spawn and obtain an actor instance, you must use a {@link Topology} implementation.
 *
 * @author Sergio Bossa
 */
public interface Actor {

    /**
     * Hot handler swapping: replaces the old handler with the given one, eventually calling the {@link com.googlecode.actorom.annotation.OnSwap} method
     * on the new one (if any).
     *
     * @param handler The new handler to swap.
     */
    public void swap(Object handler);

    /**
     * Send a message to this actor.
     *
     * @param message The message instance to send.
     */
    public void send(Object message);

    /**
     * Send a message to this actor, returning a {@link FutureResult} which can be used to wait for the message
     * computation and its result.
     *
     * @param message The message instance to send.
     * @param timeout The {@link FutureResult} timeout.
     * @param unit The {@link FutureResult} timeout unit.
     * @return A {@link FutureResult} associated to the message to send.
     */
    public FutureResult send(Object message, long timeout, TimeUnit unit);

    /**
     * Link this actor to the given actor instance.<br>
     * You can only link actors with neighbor addresses (see {@link Address#isNeighborOf(Address)}), that is, actors belonging to the same topology.<br>
     * Links are unidirectional: linking the same actors, in the same direction, more than one time has no effect.<br>
     * Actors send an {@link ExitActorMessage} to their links when they are killed or fail.
     *
     * @param actor The actor to link to.
     */
    public void link(Actor actor);

    /**
     * Unlink this actor from the given actor instance.<br>
     * Unlinking the same actors, in the same direction, more than one time has no effect.
     *
     * @param actor The actor to unlink.
     */
    public void unlink(Actor actor);

    /**
     * Get the {@link Address} of this actor.
     *
     * @return This actor's address.
     */
    public Address getAddress();

    /**
     * Return this actor's activity status: active actors can process messages and link to other actors.
     *
     * @return True if active, false otherwise.
     */
    public boolean isActive();
}
